///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 31 2019)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
//=======================================================================//
//= Include files.													    =//
//=======================================================================//
#include "MainWindow.h"
#include "SettingDialog.h"
#include "TextToolWindow.h"
#include "FontToolWindow.h"
#include "ImageToolWindow.h"
#include "Debug.h"
#include "Utility.h"
#include "ResizeDialog.h"
#include <wx/panel.h>
#include <wx/filedlg.h>
#include <wx/msgdlg.h>

//=======================================================================//
//= Data type define.                                                   =//
//=======================================================================//
enum MAIN_STATUS_AREA_ID
{
	MAIN_STATUS_TOOL_HELP = 0,
	MAIN_STATUS_PROCESS,
	MAIN_STATUS_PROCE_STATE,
	MAIN_STATUS_OPERATE,
	MAIN_STATUE_MAX
};

//=======================================================================//
//= Global variable definition                                          =//
//=======================================================================//
const wxSize G_DEFAULT_MAIN_WINDOW_SIZE(1024, 600);

//=======================================================================//
//= Event table.													    =//
//=======================================================================//
BEGIN_EVENT_TABLE(MainWindow, wxFrame)
	EVT_TOOL(GENERAL_TOOL_NEW_TEXT_WINDOW,		MainWindow::OnNew)
	EVT_TOOL(GENERAL_TOOL_NEW_FONT_WINDOW,		MainWindow::OnNew)
	EVT_TOOL(GENERAL_TOOL_NEW_IMAGE_WINDOW,		MainWindow::OnNew)
	EVT_TOOL(GENERAL_TOOL_OPEN_WORK,			MainWindow::OnOpen)
	EVT_TOOL(GENERAL_TOOL_SAVE_WORK,			MainWindow::OnSave)
	EVT_TOOL(GENERAL_TOOL_SETTINGS,				MainWindow::OnSettings)
	EVT_TOOL(GENERAL_TOOL_START,				MainWindow::OnStart)
	EVT_TOOL(GENERAL_TOOL_CANCEL,				MainWindow::OnCancel)
	EVT_TOOL(GENERAL_TOOL_EXPORT_DATA,			MainWindow::OnExportData)
	EVT_TOOL(FONT_TOOL_BAR,						MainWindow::OnFontUpdate)
	EVT_WORK_START(ID_WORK_THREAD,				MainWindow::OnWorkStart)
	EVT_WORK_END(ID_WORK_THREAD,				MainWindow::OnWorkStop)
	EVT_TEXT_CONV(ID_WORK_THREAD,				MainWindow::TextConvNotice)
	EVT_IMAGE_CONV(ID_WORK_THREAD,				MainWindow::ImageConvNotice)
	EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY,		MainWindow::WindowSelection)
	EVT_AUINOTEBOOK_PAGE_CLOSED(wxID_ANY,		MainWindow::WindowClosed)
	EVT_SIZE(MainWindow::OnSizeChanged)
	EVT_MAXIMIZE(MainWindow::OnMaximize)
	EVT_CLOSE(MainWindow::OnClose)
END_EVENT_TABLE()

//=======================================================================//
//= Function define.										            =//
//=======================================================================//
MainWindow::MainWindow(wxWindow* pclsParent, wxWindowID iID)
: wxFrame(pclsParent, iID, wxT("Simple Pixel Tools"), wxDefaultPosition, G_DEFAULT_MAIN_WINDOW_SIZE, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	/* Initialize frame. */
	SetSizeHints(G_DEFAULT_MAIN_WINDOW_SIZE);
	m_clsLayoutMgr.SetManagedWindow(this);
	m_clsLayoutMgr.SetFlags(wxAUI_MGR_DEFAULT);
	m_pclsWindowMgr = nullptr;

	/* Create general tool bar. */
	m_pclsGeneralToolBar = new GeneralToolBar(this);
	m_clsLayoutMgr.AddPane(m_pclsGeneralToolBar, wxAuiPaneInfo().Name(wxT("General Toolbar")).Caption(wxT("Font Tools")).CaptionVisible(false).CloseButton(false)
						.ToolbarPane().Top().Dock().Fixed().Gripper().BottomDockable(false).LeftDockable(false).RightDockable(false).Floatable(false));

	/* Create font tool bar. */
	m_pclsFontToolsBar = new FontToolBar(this, FONT_TOOL_BAR);
	m_clsLayoutMgr.AddPane(m_pclsFontToolsBar, wxAuiPaneInfo().Name(wxT("FontToolsBar")).Caption(wxT("Font Tools")).CaptionVisible(false).CloseButton(false)
						.ToolbarPane().Top().Dock().Fixed().Gripper().BottomDockable(false).LeftDockable(false).RightDockable(false).Floatable(false));

	m_pclsFontToolsBarEx = new FontToolBarEx(this, FONT_TOOL_BAR);
	m_clsLayoutMgr.AddPane(m_pclsFontToolsBarEx, wxAuiPaneInfo().Name(wxT("FontToolsBarEx")).Caption(wxT("Extended Font Tools")).CaptionVisible(false).CloseButton(false)
						.ToolbarPane().Top().Dock().Fixed().Gripper().BottomDockable(false).LeftDockable(false).RightDockable(false).Floatable(false));


	/* Create AUI notebook. */
	m_pclsWindowMgr = new sptWindowMgr(this, wxID_ANY);
	m_clsLayoutMgr.AddPane(m_pclsWindowMgr, wxAuiPaneInfo().Name(wxT("ChildrenNoetbook")).Caption(wxT("Work Windows")).CaptionVisible(false).CloseButton(false)
						.Center().Dock().PinButton(true).Dock().Resizable().BottomDockable(false).LeftDockable(false).RightDockable(false).Floatable(false).FloatingSize(wxDefaultSize) );

	/* Create status bar. */
	if(nullptr != CreateStatusBar(MAIN_STATUE_MAX, wxSTB_DEFAULT_STYLE, 0))
	{
		int arriStatusWidths[MAIN_STATUE_MAX];
		/* Set status width. */
		arriStatusWidths[MAIN_STATUS_TOOL_HELP] = 250;	/* For tools help. */
		arriStatusWidths[MAIN_STATUS_PROCESS] = 150;	/* For process bar. */
		arriStatusWidths[MAIN_STATUS_PROCE_STATE] = 75;     /* For Process state. */
		arriStatusWidths[MAIN_STATUS_OPERATE] = 125;	/* For operate notice. */
		wxFrame::SetStatusWidths(MAIN_STATUE_MAX, arriStatusWidths);

		m_pclsProcessBar = new wxGauge(wxFrame::GetStatusBar(), wxID_ANY, 100);
		_resetProcessBar();
	}

	/* Output panel. */
	m_pclsOutput = new OutputTextCtrl(this, wxID_ANY);
	m_clsLayoutMgr.AddPane(m_pclsOutput, wxAuiPaneInfo().Name(wxT("TestPanel")).MinSize(wxSize(-1, 200))
						.Bottom().Dock().Gripper().Floatable(true).Gripper(false)
						.Caption(wxT("Output")).CaptionVisible(true).CloseButton(true)
						.BottomDockable(true).TopDockable(false).LeftDockable(false).RightDockable(false).Floatable(false));

	Centre(wxBOTH);
	m_clsLayoutMgr.Update();
}

MainWindow::~MainWindow(void)
{
	m_clsLayoutMgr.UnInit();

}

void MainWindow::_resetProcessBar(void)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxStatusBar*			pclsStatusBar = GetStatusBar();
	wxRect					clsProcessBarRect;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if((nullptr != pclsStatusBar) && (nullptr != m_pclsProcessBar))
	{
		(void)pclsStatusBar->GetFieldRect(MAIN_STATUS_PROCESS, clsProcessBarRect);
		m_pclsProcessBar->SetPosition(clsProcessBarRect.GetPosition());
		m_pclsProcessBar->SetSize(clsProcessBarRect.GetSize());
	}
}

void MainWindow::_setProcessStatusBarText(const wxString& cstrText)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxStatusBar*			pclsStatusBar;

	/*----------------------------------*/
	/* Initialize						*/
	/*----------------------------------*/
	pclsStatusBar =			GetStatusBar();

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(nullptr != pclsStatusBar)
	{
		pclsStatusBar->SetStatusText(cstrText, 2);
	}
}

bool MainWindow::_openFile(void)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxFileDialog			clsOpenFileDialog(this, wxT("Open image file."), wxEmptyString, wxEmptyString,
										//wxT("Bitmap file (*.bmp)|*.bmp|Text file (*.txt)|*.txt|All files (*.*)|*.*"), wxFD_OPEN|wxFD_FILE_MUST_EXIST);
										wxT("Text file (*.txt)|*.txt|Bitmap file (*.bmp)|*.bmp"), wxFD_OPEN|wxFD_FILE_MUST_EXIST);
	wxFileName				clsFileName;
	bool					bReturn = false;
	sptChildWindowBase*		pclsNewWindow;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(wxID_OK == clsOpenFileDialog.ShowModal())
    {
    	/* Get file path. */
		clsFileName = clsOpenFileDialog.GetPath();

		/* Search if file was be opened. */
		pclsNewWindow = m_pclsWindowMgr->SearchOpenedFile(clsFileName.GetFullPath());

		do
		{
			if(nullptr != pclsNewWindow)
			{
				/* Select the window which opened the file. */
				m_pclsWindowMgr->SelectWindow(pclsNewWindow);
				break;
			}
			if(clsFileName.GetExt().IsSameAs(wxT("txt"), false))
			{
				/* A text file will be opened. */
				pclsNewWindow = new TextToolWindow(m_pclsWindowMgr, clsFileName.GetFullPath());
				m_pclsWindowMgr->AddWindow(pclsNewWindow, true, wxBITMAP_PNG(RES_ID_TOOL_NEW_TEXT_WINDOW));
				break;
			}
			if(clsFileName.GetExt().IsSameAs(wxT("bmp"), false))
			{
				/* A bitmap file will be opened. */
				pclsNewWindow = new ImageToolWindow(m_pclsWindowMgr, clsFileName.GetFullPath());
				m_pclsWindowMgr->AddWindow(pclsNewWindow, true, wxBITMAP_PNG(RES_ID_TOOL_NEW_IMAGE_WINDOW));
				break;
			}
		}while(false);

		if(pclsNewWindow)
		pclsNewWindow->UpdateTitle();
    }

    return bReturn;
}

bool MainWindow::_newImageWindow(void)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	ResizeDialog			clsResizeDialog(this);
	ImageToolWindow*		pclsNewImageWindow = nullptr;
	bool					bReturn;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	/* Set default size. */
	clsResizeDialog.SetSizeValue(wxSize(128, 64));

	/* Show new creation dialog. */
    if(wxID_OK == clsResizeDialog.ShowModal())
    {
		/* Create new window. */
		pclsNewImageWindow = new ImageToolWindow(m_pclsWindowMgr, clsResizeDialog.GetSizeValue());
		if(nullptr != pclsNewImageWindow)
		{
			bReturn = m_pclsWindowMgr->AddWindow(pclsNewImageWindow, true, wxBITMAP_PNG(RES_ID_TOOL_NEW_IMAGE_WINDOW));
		}
		else
		{
			bReturn = false;
		}
    }
    else
	{
		bReturn = false;
	}

	return bReturn;
}

void MainWindow::OnSizeChanged(wxSizeEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	_resetProcessBar();

    if(m_pclsWindowMgr)
    {
    	if(m_pclsWindowMgr->GetPageCount() > 0)
		{
			wxPostEvent(m_pclsWindowMgr->GetPage(m_pclsWindowMgr->GetSelection()), clsEvent);
		}
    }
	clsEvent.Skip();
}

void MainWindow::OnMaximize(wxMaximizeEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxSizeEvent				clsResizeEvent;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	_resetProcessBar();

	if(m_pclsWindowMgr)
	{
		for(size_t sWinIdx=0; sWinIdx<m_pclsWindowMgr->GetPageCount(); sWinIdx++)
		{
			clsResizeEvent.SetSize(m_pclsWindowMgr->GetPage(m_pclsWindowMgr->GetSelection())->GetSize());
			wxPostEvent(m_pclsWindowMgr->GetPage(m_pclsWindowMgr->GetSelection()), clsResizeEvent);
		}
	}
	clsEvent.Skip();
}

void MainWindow::OnClose(wxCloseEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	// Destroy frame.
    Destroy();

	clsEvent.Skip();
}

void MainWindow::OnNew(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	sptChildWindowBase*     pclsNewChildWindow = nullptr;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	switch(clsEvent.GetId())
	{
		case GENERAL_TOOL_NEW_TEXT_WINDOW:
		{
			pclsNewChildWindow = new TextToolWindow(m_pclsWindowMgr);
			m_pclsWindowMgr->AddWindow(pclsNewChildWindow, true, wxBITMAP_PNG(RES_ID_TOOL_NEW_TEXT_WINDOW));
			break;
		}
		case GENERAL_TOOL_NEW_FONT_WINDOW:
		{
			//new FontToolWindow(this);
			break;
		}
		case GENERAL_TOOL_NEW_IMAGE_WINDOW:
		{
			_newImageWindow();
			break;
		}
		default:
		{
			/* Undefined action, do nothing. */
		}
	}
}

void MainWindow::OnOpen(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	/* Open file. */
	_openFile();

	clsEvent.Skip();
}

void MainWindow::OnSave(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	sptChildWindowBase*		pclsWindow = m_pclsWindowMgr->GetSelectedWindow();

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(nullptr != pclsWindow)
	{
		if(pclsWindow->SaveFile())
		{
			/* Update label title text. */
			m_pclsWindowMgr->UpdateTitle(m_pclsWindowMgr->GetSelection());
		}
	}

	clsEvent.Skip();
}

void MainWindow::OnSettings(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	SettingDialog			clsNewDialog(this);
	int						iDlgResult = wxID_NONE;
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	clsNewDialog.SetConfiguration(ConfigurationInstance());
	// Show setting dialog window.
	iDlgResult = clsNewDialog.ShowModal();
	if(wxID_OK == iDlgResult)
	{
		// Save the new configuration.
		ConfigurationInstance() = clsNewDialog.GetSettings();
		// Send new configuration update event to each child.
		if((nullptr == m_pclsWindowMgr) || (0 == m_pclsWindowMgr->GetPageCount()))
		{
			wxLogInfo("No working window.");
		}
		else
		{
			wxCommandEvent clsNoticeEvent(GlobalSettingUpdateEvent, EVT_SETTING_CHANGED);
			for(size_t sWinIdx=0; sWinIdx<m_pclsWindowMgr->GetPageCount(); sWinIdx++)
			{
				wxPostEvent(m_pclsWindowMgr->GetPage(sWinIdx), clsNoticeEvent);
			}
		}
	}
}

void MainWindow::OnStart(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	sptChildWindowBase*		pclsActivedWindow = m_pclsWindowMgr->GetWindow(m_pclsWindowMgr->GetSelection());

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	m_pclsOutput->Clear();
	if(nullptr != pclsActivedWindow)
	{
		pclsActivedWindow->StartProcess(this);
	}
	clsEvent.Skip();
}

void MainWindow::OnCancel(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	(void)WorkThreadMgr::Instance().StopThread();
	clsEvent.Skip();
}

void MainWindow::OnExportData(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxFileDialog			clsSaveFileDialog(this, wxT("Save to file."), wxEmptyString, wxEmptyString,
										wxT("Text file (*.txt)|*.txt|Binary file (*.bin)|*.bin|All files (*.*)|*.*"), wxFD_SAVE);
	bool					bReturn;
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
    if(wxID_OK == clsSaveFileDialog.ShowModal())
    {
    	wxFileName clsFilename = clsSaveFileDialog.GetPath();
    	if(clsFilename.GetExt().IsSameAs(wxT("txt"), false))
		{
			/* Save as text file. */
			bReturn = m_pclsOutput->SaveAsTextFile(clsFilename.GetFullPath());
		}
		else if(clsFilename.GetExt().IsSameAs(wxT("bin"), false))
		{
			/* Save as binary file. */
			bReturn = m_pclsOutput->SaveAsBinaryFile(clsFilename.GetFullPath());
		}

		if(false == bReturn)
		{
			wxMessageBox(wxT("Export data failed."), wxT("Error"), wxOK|wxCENTRE|wxICON_ERROR);
		}
    }

	clsEvent.Skip();
}

void MainWindow::OnFontUpdate(wxCommandEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxCommandEvent			clsNoticeEvent(PaintFontUpdateEvent,  EVT_PAINT_FONT_CHANGED);

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	DBG_LOG(wxT("Font settings updated."));
	if(nullptr != m_pclsWindowMgr)
	{
		for(size_t sPageIdx=0; sPageIdx < m_pclsWindowMgr->GetPageCount(); sPageIdx++)
		{
			wxPostEvent(m_pclsWindowMgr->GetPage(sPageIdx), clsNoticeEvent);
		}
	}
	clsEvent.StopPropagation();
}

void MainWindow::OnWorkStart(WorkStartEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	m_pclsGeneralToolBar->OnProcessStart();
	m_pclsFontToolsBar->OnProcessStart();
	m_pclsFontToolsBarEx->OnProcessStart();
	m_pclsProcessBar->SetRange(clsEvent.GetTotal());
	_setProcessStatusBarText(wxT("Processing..."));
}


void MainWindow::OnWorkStop(WorkEndEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	m_pclsGeneralToolBar->OnProcessStop();
	m_pclsFontToolsBar->OnProcessStop();
	m_pclsFontToolsBarEx->OnProcessStop();
	m_pclsProcessBar->SetValue(m_pclsProcessBar->GetRange());
	_setProcessStatusBarText(wxT("Done."));
}

void MainWindow::TextConvNotice(TextConvEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	_setProcessStatusBarText(wxString::Format(wxT("%d/%d"), clsEvent.GetProcessed(), clsEvent.GetTotal()));
	m_pclsProcessBar->SetValue(clsEvent.GetProcessed());
	m_pclsOutput->AppendData(clsEvent.GetData());

	clsEvent.Skip();
}

void MainWindow::ImageConvNotice(ImageConvEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	m_pclsOutput->AppendData(clsEvent.GetData());
	clsEvent.Skip();
}

void MainWindow::WindowSelection(wxAuiNotebookEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(clsEvent.GetSelection() != wxNOT_FOUND)
    {
        SetLabel(m_pclsWindowMgr->GetWindow(clsEvent.GetSelection())->GetFilePath());
        if(WorkThreadMgr::Instance().IsRunning())
        {
            m_pclsGeneralToolBar->Working(false);
        }
        else
        {
            m_pclsGeneralToolBar->Working(true);
        }
    }
	else
	{
		m_pclsGeneralToolBar->Working(true);
	}
	clsEvent.Skip();
}

void MainWindow::WindowClosed(wxAuiNotebookEvent& clsEvent)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(0 == m_pclsWindowMgr->GetPageCount())
	{
		m_pclsGeneralToolBar->Working(false);
	}
}
